package com.yf.thumbbackend.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yf.thumbbackend.constant.ThumbConstant;
import com.yf.thumbbackend.entity.Blog;
import com.yf.thumbbackend.entity.Thumb;
import com.yf.thumbbackend.entity.User;
import com.yf.thumbbackend.entity.dto.DoThumbRequest;
import com.yf.thumbbackend.exception.BusinessException;
import com.yf.thumbbackend.manager.cache.CacheManager;
import com.yf.thumbbackend.mapper.ThumbMapper;
import com.yf.thumbbackend.service.BlogService;
import com.yf.thumbbackend.service.ThumbService;
import com.yf.thumbbackend.service.UserService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

/**
 * @author 随风
 * @date 2025/4/21 18:28
 * @description ThumbServiceImplCache
 */
@Service("thumbService")
@RequiredArgsConstructor
@Slf4j
public class ThumbServiceImplCache extends ServiceImpl<ThumbMapper, Thumb> implements ThumbService {

    @Resource
    private BlogService blogService;

    private final RedisTemplate<String,Object> redisTemplate;

    private final UserService userService;

    private final TransactionTemplate transactionTemplate;

    private final CacheManager cacheManager;

    @Override
    public Boolean doThumb(DoThumbRequest doThumbRequest, HttpServletRequest request) {
        //校验
        if (doThumbRequest == null || doThumbRequest.getId() == null){
            throw new BusinessException(400, "参数错误");
        }
        //获取用户id
        Long userId = userService.getLoginUser(request).getId();

        //加锁
        synchronized (userId.toString().intern()){
            //编程时事务
            transactionTemplate.execute(status -> {
                //获取博客id
                Long blogId = doThumbRequest.getId();
                //判断是否已经点赞
                if (hasThumb(blogId,userId)){
                    throw new BusinessException(400, "已经点赞");
                }
                //点赞
                boolean update =blogService.lambdaUpdate()
                        .setSql("thumbCount = thumbCount + 1")
                        .eq(Blog::getId, blogId)
                        .update();

                Thumb thumb = new Thumb();
                thumb.setBlogId(blogId);
                thumb.setUserId(userId);
                boolean success =  update && this.save(thumb);
                if (success){
                    //更新缓存
                    String hashKey = ThumbConstant.USER_THUMB_KEY_PREFIX + userId;
                    String fieldKey = blogId.toString();
                    Long realThumbId = thumb.getId();
                    redisTemplate.opsForHash().put(hashKey,fieldKey,realThumbId);
                    cacheManager.putIfPresent(hashKey, fieldKey,realThumbId);
                }
                return success;
            });
        }
        return true;
    }

    @Override
    public Boolean undoThumb(DoThumbRequest doThumbRequest, HttpServletRequest request) {
        if (doThumbRequest == null || doThumbRequest.getId() == null) {
            throw new RuntimeException("参数错误");
        }
        User loginUser = userService.getLoginUser(request);
        // 加锁
        synchronized (loginUser.getId().toString().intern()) {

            // 编程式事务
            return transactionTemplate.execute(status -> {
                Long blogId = doThumbRequest.getId();
                Object thumbIdObj = cacheManager.get(ThumbConstant.USER_THUMB_KEY_PREFIX + loginUser.getId(), blogId.toString());
                if (thumbIdObj == null || thumbIdObj.equals(ThumbConstant.UN_THUMB_CONSTANT)) {
                    throw new RuntimeException("用户未点赞");
                }
                boolean update = blogService.lambdaUpdate()
                        .eq(Blog::getId, blogId)
                        .setSql("thumbCount = thumbCount - 1")
                        .update();
                boolean success = update && this.removeById((Long)thumbIdObj);

                // 点赞记录从 Redis 删除
                if (success) {
                    String hashKey = ThumbConstant.USER_THUMB_KEY_PREFIX + loginUser.getId();
                    String fieldKey = blogId.toString();
                    redisTemplate.opsForHash().delete(hashKey, fieldKey);
                    cacheManager.putIfPresent(hashKey, fieldKey, ThumbConstant.UN_THUMB_CONSTANT);
                }
                return success;
            });
        }
    }

    @Override
    public Boolean hasThumb(Long blogId, Long userId) {
        Object o = cacheManager.get(ThumbConstant.USER_THUMB_KEY_PREFIX + userId, blogId.toString());
        if (o == null){
            return false;
        }
        Long thumbId = (Long) o;

        return !thumbId .equals(ThumbConstant.UN_THUMB_CONSTANT);

    }
}
